package com.ztgf.user.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ztgf.common.constant.CommonParameter;
import com.ztgf.common.constant.Result;
import com.ztgf.common.enums.CodeEnum;
import com.ztgf.common.utils.DateUtils;
import com.ztgf.common.utils.Md5Utils;
import com.ztgf.db.utils.RedisUtil;
import com.ztgf.shopping.models.bo.shop.ShopQualificationApiSaveBO;
import com.ztgf.shopping.models.dto.audit.AuditDTO;
import com.ztgf.shopping.models.dto.shop.*;
import com.ztgf.shopping.models.enums.ShoppingCodeEnum;
import com.ztgf.shopping.models.service.audit.IAuditService;
import com.ztgf.shopping.models.service.shop.*;
import com.ztgf.shopping.models.vo.audit.RegisterVO;
import com.ztgf.sms.models.bo.EmailSendBO;
import com.ztgf.sms.models.bo.SmsInfoBO;
import com.ztgf.sms.models.service.IEmailInfoService;
import com.ztgf.sms.models.service.ISmsInfoService;
import com.ztgf.sys.models.bo.SysRoleSaveBO;
import com.ztgf.sys.models.dto.SysDictDTO;
import com.ztgf.sys.models.service.ISysDictService;
import com.ztgf.sys.models.service.ISysRoleService;
import com.ztgf.user.common.config.YmlConfig;
import com.ztgf.user.mapper.UserLoginMapper;
import com.ztgf.user.models.bo.UserLoginBO;
import com.ztgf.user.models.bo.UserLoginSaveBO;
import com.ztgf.user.models.bo.UserLoginSubSaveBO;
import com.ztgf.user.models.bo.UserLoginUpdateBO;
import com.ztgf.user.models.constant.UserConstant;
import com.ztgf.user.models.dto.*;
import com.ztgf.user.models.service.IUserLoginService;
import com.ztgf.user.models.vo.UserLoginVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;



/**
 * 用户登录表控制器
 *
 * @author zhanghualang
 * @Date 2020-05-28 17:42:53
 */
@DubboService
@Slf4j
public class UserLoginServiceImpl extends ServiceImpl<UserLoginMapper, UserLoginDTO> implements IUserLoginService {


    @Value(value = "${sms-url}")
    private String smsUrl;
    @DubboReference
    private ISmsInfoService iSmsInfoService;
    @Autowired
    @Lazy
    private UserInfoServiceImpl iUserInfoService;
    @Autowired
    private UserRoleRelationServiceImpl iUserRoleRelationService;
    @Autowired
    private UserImServiceImpl iUserImService;
    @DubboReference
    private IShopInfoService iShopInfoService;
    @DubboReference
    private IShopUserRelationService iShopUserRelationService;
    @DubboReference
    private IShopQualificationService iShopQualificationService;
    @Autowired
    private UserLoginLogServiceImpl iUserLoginLogService;
    @DubboReference
    private IEmailInfoService iEmailInfoService;
    @DubboReference
    private IShopInfoAuditService iShopInfoAuditService;
    @DubboReference
    private IShopInfoAuditLogService iShopInfoAuditLogService;
    @DubboReference
    private IShopQualificationAuditService iShopQualificationAuditService;
    @DubboReference
    private IShopBlacklistService iShopBlacklistService;
    @DubboReference
    private ISysDictService iSysDictService;
    @DubboReference
    private ISysRoleService iSysRoleService;
    @DubboReference
    private IAuditService auditService;
    @Resource
    private YmlConfig ymlConfig;
    @Autowired
    private RedisUtil redisUtil;



    /**
     * 设置用户session 和用户信息
     *
     * @param userInfoDTO 用户信息
     * @param sessionId
     * @return
     */
    @Override
    public boolean setUserBySessionId(UserInfoDTO userInfoDTO, String sessionId) {
        //判断之前id和session是否关联
        Integer source = CommonParameter.getHeadParamsBO().getSource();
        redisUtil.setIdSessionRelation(userInfoDTO.getId().toString(), sessionId, source.toString());
        redisUtil.setSession(sessionId, userInfoDTO, source.toString());
        return true;
    }

    /**
     * 根据session获取用户信息
     *
     * @param sessionId
     * @return
     */
    @Override
    public UserInfoDTO getUserBySessionId(String sessionId) {
        Object bean = redisUtil.getSession(sessionId, CommonParameter.getHeadParamsBO().getSource().toString());
        if (bean != null && bean instanceof UserInfoDTO) {
            return (UserInfoDTO) bean;
        }
        return null;
    }

    @Override
    public void resetSession(Long userId) {
        Object obj = redisUtil.getIdSessionRelation(userId.toString(), CommonParameter.getHeadParamsBO().getSource().toString());
        if (obj != null) {
            redisUtil.removeIdSession(obj.toString(), CommonParameter.getHeadParamsBO().getSource().toString());
            redisUtil.removeSession(obj.toString(), CommonParameter.getHeadParamsBO().getSource().toString());
        }
    }

    @Override
    //@LcnTransaction
    //@Transactional
    public UserInfoDTO add(UserLoginSaveBO saveBO) {

        // 事务预留
        /**
         * 保存用户信息表信息
         */
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        Long userInfoId = ymlConfig.getPkId();
        userInfoDTO.setId(userInfoId);
        userInfoDTO.setName(saveBO.getName());//公司名称
        userInfoDTO.setContactName(saveBO.getContactName());//联系人名称
        userInfoDTO.setAddress(saveBO.getAddress());//保存公司地址
        iUserInfoService.insert(userInfoDTO);//状态默认 0创建。类型默认 0主账号

        /*
         * 保存用户登录表
         */
        UserLoginDTO dto = new UserLoginDTO();
        BeanUtils.copyProperties(saveBO, dto);
        String salt = Md5Utils.createSalt();
        dto.setPassword(Md5Utils.MD5Encode(dto.getPassword(), salt));//密码转换后加入盐大写后加密
        dto.setSalt(salt);
        Long id = ymlConfig.getPkId();
        dto.setId(id);
        dto.setUserId(userInfoId);//保存userID
        this.insert(dto);

        /*
         * 保存角色关系表
         */
        UserRoleRelationDTO userRoleRelationDTO = new UserRoleRelationDTO();
        Long userRoleRelationId = ymlConfig.getPkId();
        userRoleRelationDTO.setId(userRoleRelationId);
        userRoleRelationDTO.setUserId(userInfoId);//用户ID
        userRoleRelationDTO.setRoleId(Long.parseLong(iSysDictService.getManagerValue()));//权限，默认店主
        iUserRoleRelationService.insert(userRoleRelationDTO);

        /**
         * 保存IM账号表
         */
        UserImDTO userImDTO = new UserImDTO();
        userImDTO.setId(ymlConfig.getPkId());
        userImDTO.setUserId(userInfoId);
        iUserImService.insert(userImDTO);//类型默认买家

        UserImDTO userImSDTO = new UserImDTO();
        userImSDTO.setId(ymlConfig.getPkId());
        userImSDTO.setUserId(userInfoId);
        userImSDTO.setType(1);//卖家
        iUserImService.insert(userImSDTO);//类型默认买家

        /**
         * 添加审核流程
         * 1.添加店铺审核表
         * 2.添加日志表
         * 3.添加资质审核表
         */

        /**
         * 添加店铺审核表
         */
        ShopInfoAuditDTO shopInfoAuditDTO = new ShopInfoAuditDTO();
        Long shopInfoAuditId = ymlConfig.getPkId();
        shopInfoAuditDTO.setId(shopInfoAuditId);
        shopInfoAuditDTO.setUserId(userInfoId);
        shopInfoAuditDTO.setCreateUserId(userInfoId);
        shopInfoAuditDTO.setName(saveBO.getName());//公司名称
        shopInfoAuditDTO.setAddress(saveBO.getAddress());//公司名称
        if (saveBO.getInvitationCode() != null) {
            shopInfoAuditDTO.setInvitationCode(saveBO.getInvitationCode());//邀请码
        }
        shopInfoAuditDTO.setLegalPerson(saveBO.getLegalPerson());//法人
        shopInfoAuditDTO.setIdCard(saveBO.getIdCard());//法人身份证号
        shopInfoAuditDTO.setIdCardType(saveBO.getIdCardType());//法人证件类型
        shopInfoAuditDTO.setCreditCode(saveBO.getCreditCode());//统一信用代码
        shopInfoAuditDTO.setPayMobile(saveBO.getPayMobile());//财务主管手机号
        shopInfoAuditDTO.setType(0);//审核类型 0注册，1开店，2资质变更，3新增品牌，4新增类目
        shopInfoAuditDTO.setStatus(0);//审核状态 0审核中，1审核通过，2审核打回，3审核不通过
        iShopInfoAuditService.insert(shopInfoAuditDTO);

        /**
         * 添加审核日志表
         */
        ShopInfoAuditLogDTO shopInfoAuditLogDTO = new ShopInfoAuditLogDTO();
        Long shopInfoAuditLogId = ymlConfig.getPkId();
        shopInfoAuditLogDTO.setId(shopInfoAuditLogId);
        shopInfoAuditLogDTO.setCreateUserId(userInfoId);
        shopInfoAuditLogDTO.setUserId(userInfoId);
        shopInfoAuditLogDTO.setShopAuditId(shopInfoAuditId);
        shopInfoAuditLogDTO.setStatus(0);//审核状态 0审核中(提交审核)，1审核通过，2审核打回，3审核不通过
        shopInfoAuditLogDTO.setType(0);//审核类型 0注册，1开店，2资质变更，3新增品牌，4新增类目
        iShopInfoAuditLogService.insert(shopInfoAuditLogDTO);

        /**
         * 添加资质审核表
         */
        List<ShopQualificationApiSaveBO> shopQualificationApiSaveBOList = JSON.parseArray(saveBO.getShopQualificationApiSaveBOList(), ShopQualificationApiSaveBO.class);
        for (ShopQualificationApiSaveBO shopQualificationApiSaveBO : shopQualificationApiSaveBOList) {
            ShopQualificationAuditDTO shopQualificationAuditDTO = new ShopQualificationAuditDTO();
            shopQualificationAuditDTO.setId(ymlConfig.getPkId());
            shopQualificationAuditDTO.setCreateUserId(userInfoId);
            shopQualificationAuditDTO.setUserId(userInfoId);
            shopQualificationAuditDTO.setShopAuditId(shopInfoAuditId);
            shopQualificationAuditDTO.setFileUrl(shopQualificationApiSaveBO.getFileUrl());//图片url
            shopQualificationAuditDTO.setBeginDate(shopQualificationApiSaveBO.getBeginDate());
            shopQualificationAuditDTO.setEndDate(shopQualificationApiSaveBO.getEndDate());
            //类型 0营业执照，1法人身份证，3开户许可证，4商标注册证书，5续展证明文件，6ISO认证书，7品牌授权书、
            shopQualificationAuditDTO.setType(shopQualificationApiSaveBO.getType());
            //审核类型 0注册，1开店，2资质变更，3新增品牌，4新增类目
            shopQualificationAuditDTO.setAuditType(0);
            shopQualificationAuditDTO.setStatus(0);//审核状态 0审核中，1审核通过，2审核打回，3审核不通过
            iShopQualificationAuditService.insert(shopQualificationAuditDTO);
        }

        return userInfoDTO;
    }

    @Override
    public UserLoginDTO getLogin(UserLoginBO userLoginBO) {
        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("mobile", userLoginBO.getAccount()).or().eq("email", userLoginBO.getAccount());

        return this.selectOne(wrapper);
    }

    @Override
    public UserInfoDTO getUserInfo(UserLoginBO userLoginBO) {
        UserLoginDTO userLoginDTO = getLogin(userLoginBO);
        //用户信息
        UserInfoDTO userInfoDTO = iUserInfoService.selectById(userLoginDTO.getUserId());
        //添加日志
        UserLoginLogDTO userLoginLogDTO = new UserLoginLogDTO();
        userLoginLogDTO.setId(ymlConfig.getPkId());
        userLoginLogDTO.setUserId(userInfoDTO.getId());
        userLoginLogDTO.setUserName(userInfoDTO.getName());//记录公司人
        userLoginLogDTO.setType(0);//登录状态 0登录、1登出

        if (userLoginDTO.getPassword().equals(Md5Utils.MD5Encode(userLoginBO.getPassword(), userLoginDTO.getSalt()))) {
            //登录成功
            userLoginLogDTO.setResultCode(0);//登录返回值 0成功，其他值失败
            iUserLoginLogService.insert(userLoginLogDTO);
            //更新验证次数及状态
            UserLoginDTO newUserLoginDTO = new UserLoginDTO();
            newUserLoginDTO.setId(userLoginDTO.getId());
            newUserLoginDTO.setVerifyNum(5);
            newUserLoginDTO.setStatus(0);
            this.updateById(newUserLoginDTO);
            return userInfoDTO;
        } else {
            //登陆失败
            userLoginLogDTO.setResultCode(1);//登录返回值 0成功，其他值失败
            iUserLoginLogService.insert(userLoginLogDTO);
            return null;
        }
    }

    @Override
    public ShopInfoDTO getShopInfo(Long userId) {
        //店员表
        Wrapper<ShopUserRelationDTO> shopUserWrapper = new EntityWrapper<>();
        shopUserWrapper.eq("user_id", userId);
        ShopUserRelationDTO shopUserRelationDTO = iShopUserRelationService.selectOne(shopUserWrapper);
        if (shopUserRelationDTO == null) {
            return null;
        }
        return iShopInfoService.selectById(shopUserRelationDTO.getShopId());
    }

    @Override
    public ShopBlacklistDTO getByCompanyName(String name, Integer type) {
        return iShopBlacklistService.getByCompanyName(name, type);
    }

    @Override
    public Result updateQuit(String sessionId) {
        UserInfoDTO userInfoDTO = this.getUserBySessionId(sessionId);
        if (userInfoDTO == null) {
            return new Result<>();
        }
        //登录日志
        UserLoginLogDTO userLoginLogDTO = new UserLoginLogDTO();
        userLoginLogDTO.setId(ymlConfig.getPkId());
        userLoginLogDTO.setUserId(userInfoDTO.getId());
        userLoginLogDTO.setUserName(userInfoDTO.getName());//记录公司人
        userLoginLogDTO.setType(1);//登录状态 0登录、1登出
        iUserLoginLogService.insert(userLoginLogDTO);

        //清除session
        redisUtil.removeSession(sessionId, CommonParameter.getHeadParamsBO().getSource().toString());
        redisUtil.removeIdSession(userInfoDTO.getId().toString(), CommonParameter.getHeadParamsBO().getSource().toString());
        return new Result<>();
    }

    @Override
    public boolean getSmsCaptcha(String mobile, String captcha, Integer type) {
        //判断使用的是dubbo还是api
        SysDictDTO dto = iSysDictService.getByName(UserConstant.DUBBO_OR_API);
        //0dubbo ,1api .默认0
        if (dto != null && dto.getValue().equals("1")) {
            RestTemplate restTemplate = new RestTemplate();
            String url = smsUrl + "/sms-client/api/sms/getCaptcha";
            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();//hashmap无法解析
            map.add("mobile", mobile);
            map.add("content", captcha);
            map.add("captchaType", type.toString());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);//fromdata 方式发送
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
            ResponseEntity<Result> responseEntity = restTemplate.postForEntity(url, request, Result.class);
            try {
                return responseEntity.getBody().getCode() == 0;
            } catch (Exception e) {
                return false;
            }
        } else {
            SmsInfoBO smsInfoBO = new SmsInfoBO();
            smsInfoBO.setMobile(mobile);
            smsInfoBO.setContent(captcha);
            smsInfoBO.setCaptchaType(type);
            return iSmsInfoService.getCaptcha(smsInfoBO);
        }
    }

    @Override
    public Result updatePassword(UserLoginBO userLoginBO) {
        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("mobile", userLoginBO.getAccount()).or().eq("email", userLoginBO.getAccount());
        UserLoginDTO userLoginDTO = this.selectOne(wrapper);
        if (userLoginDTO == null) {
            return new Result<>(CodeEnum.FAIL_USER_200003);
        }

        if (userLoginDTO.getPassword().equals(Md5Utils.MD5Encode(userLoginBO.getPassword(), userLoginDTO.getSalt()))) {
            return new Result<>(CodeEnum.FAIL_LOGIN_2005);
        }

        UserLoginDTO newDto = new UserLoginDTO();
        newDto.setId(userLoginDTO.getId());
        String salt = Md5Utils.createSalt();
        newDto.setPassword(Md5Utils.MD5Encode(userLoginBO.getPassword(), salt));//密码加密
        newDto.setSalt(salt); //密码盐
        this.updateById(newDto);
        return new Result<>(CodeEnum.SUCCESS);
    }

    @Override
    public UserInfoDTO getLoginMobile(UserLoginDTO userLoginDTO) {
        UserLoginLogDTO userLoginLogDTO = new UserLoginLogDTO();
        UserInfoDTO userInfoDTO = iUserInfoService.selectById(userLoginDTO.getUserId());
        //添加日志
        userLoginLogDTO.setId(ymlConfig.getPkId());
        userLoginLogDTO.setUserId(userInfoDTO.getId());
        userLoginLogDTO.setUserName(userInfoDTO.getName());//记录公司人
        userLoginLogDTO.setType(0);//登录状态 0登录、1登出
        //登录成功
        userLoginLogDTO.setResultCode(0);//登录返回值 0成功，其他值失败
        iUserLoginLogService.insert(userLoginLogDTO);

        //更新验证次数及状态
        UserLoginDTO newUserLoginDTO = new UserLoginDTO();
        newUserLoginDTO.setId(userLoginDTO.getId());
        newUserLoginDTO.setVerifyNum(5);
        newUserLoginDTO.setStatus(0);
        this.updateById(newUserLoginDTO);

        return userInfoDTO;
    }

    @Override
    public UserLoginDTO getLoginByMobile(String mobile) {
        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("mobile", mobile);
        return this.selectOne(wrapper);
    }

    @Override
    public boolean updateByMobile(String mobile) {
        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("mobile", mobile);

        UserLoginDTO dto = new UserLoginDTO();
        dto.setMobile(mobile);

        return this.update(dto, wrapper);
    }

    @Override
    public UserLoginDTO getLoginByEmail(String email) {
        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("email", email);
        return this.selectOne(wrapper);
    }


    @Override
    public boolean updateByEmail(String email) {
        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("email", email);

        UserLoginDTO dto = new UserLoginDTO();
        dto.setEmail(email);

        return this.update(dto, wrapper);
    }

    @Override
    public boolean getLoginByName(String name) {
        Wrapper<UserInfoDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("name", name);

        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setName(name);

        return iUserInfoService.update(userInfoDTO, wrapper);
    }

    public boolean getLoginReturnByName(String name, Long userId) {
        UserInfoDTO userInfoDTO = iUserInfoService.selectById(userId);
        if (userInfoDTO.getName().equals(name)) {
            return false;
        }

        Wrapper<UserInfoDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("name", name);
        UserInfoDTO uiDto = new UserInfoDTO();
        uiDto.setName(name);

        return iUserInfoService.update(uiDto, wrapper);
    }

    @Override
    public boolean updateEmail(UserLoginUpdateBO bo) {
        UserLoginDTO userLoginDTO = new UserLoginDTO();

        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("user_id", bo.getUserId());
        UserLoginDTO dto = this.selectOne(wrapper);

        userLoginDTO.setId(dto.getId());
        userLoginDTO.setEmail(bo.getEmail());
        return this.updateById(userLoginDTO);
    }

    @Override
    public boolean updateMobile(UserLoginUpdateBO bo) {
        UserLoginDTO userLoginDTO = new UserLoginDTO();

        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("user_id", bo.getUserId());
        UserLoginDTO dto = this.selectOne(wrapper);

        userLoginDTO.setId(dto.getId());
        userLoginDTO.setMobile(bo.getMobile());
        return this.updateById(userLoginDTO);
    }

    @Override
    public boolean getEmailCaptcha(String email, String captcha) {
        EmailSendBO bo = new EmailSendBO();
        bo.setEmail(email);
        bo.setContext(captcha);
        return iEmailInfoService.getCaptcha(bo);
    }

    @Override
    @Async
    public void sendEmail(String email, Long id) {
        //发送激活邮件
        EmailSendBO emailInfoBO = new EmailSendBO();
        emailInfoBO.setEmail(email);
        emailInfoBO.setType(0);//类型 0.激活、1活动
        emailInfoBO.setContext(String.valueOf(id));
        iEmailInfoService.sendActiveEail(emailInfoBO);
    }

    @Override
    @Transactional
    public boolean updateContactInfo(UserLoginUpdateBO bo) {
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setId(bo.getUserId());
        userInfoDTO.setContactName(bo.getContactName());
        iUserInfoService.updateById(userInfoDTO);

        UserLoginDTO userLoginDTO = new UserLoginDTO();

        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("user_id", bo.getUserId());
        UserLoginDTO dto = this.selectOne(wrapper);

        userLoginDTO.setId(dto.getId());
        userLoginDTO.setMobile(bo.getMobile());
        userLoginDTO.setEmail(bo.getEmail());
        return this.updateById(userLoginDTO);
    }

    @Override
    public UserImDTO getImById(Long userId, Integer type) {
        Wrapper<UserImDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("user_id", userId).eq("type", type);
        return iUserImService.selectOne(wrapper);
    }

    @Override
    public boolean getActiveByEmail(String email) {

        UserLoginDTO dto = getLoginByEmail(email);
        if (dto == null) {
            return false;
        }
        UserInfoDTO userInfoDTO = iUserInfoService.selectById(dto.getUserId());
        return userInfoDTO.getEmailActive().equals(1);
    }

    @Override
    public boolean setVerifyWidth(String key, Integer xWidth) {
        return redisUtil.setVerifyWidth(key, xWidth.toString());
    }

    @Override
    public String getVerifyWidth(String key) {
        Object bean = redisUtil.getVerifyWidth(key);
        if (bean != null) {
            return (String) bean;
        }
        return "";
    }

    @Override
    public void deleteVerifyWidth(String key) {
        redisUtil.del(key);
    }

    @Override
    public int lowerVerifyNum(UserLoginDTO userLoginDTO) {
        //登录次数减一，并修改状态
        UserLoginDTO newUserLoginDTO = new UserLoginDTO();
        newUserLoginDTO.setVerifyNum(userLoginDTO.getVerifyNum() - 1);
        newUserLoginDTO.setId(userLoginDTO.getId());
        if (newUserLoginDTO.getVerifyNum().equals(0)) {
            newUserLoginDTO.setStatus(1);//锁定账号
            //设置解锁时间
            newUserLoginDTO.setUnlockTime(DateUtils.addMinute(DateUtils.getCurrentDateTime(), Integer.valueOf(iSysDictService.getByName(UserConstant.UNLOCK_TIME).getValue())));
        }
        this.updateById(newUserLoginDTO);

        return newUserLoginDTO.getVerifyNum();
    }

    @Override
    public List<UserLoginDTO> queryLock(Long minNo, Integer pageNo) {
        Wrapper<UserLoginDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("status", 1);//到期状态 0正常，1被锁定
        wrapper.ge("id", minNo);
        wrapper.orderBy("id", true);
        return baseMapper.selectPage(new Page(0, pageNo), wrapper);
    }

    @Override
    @Transactional
    public boolean addSub(UserLoginSubSaveBO saveBO) {
        /**
         * 保存用户信息表信息
         */
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        Long userInfoId = ymlConfig.getPkId();
        userInfoDTO.setId(userInfoId);
        userInfoDTO.setName(saveBO.getName());//公司名称
        userInfoDTO.setContactName(saveBO.getContactName());//联系人名称
        userInfoDTO.setType(1);//类型 0主账号。1子账号
        userInfoDTO.setStatus(1);//子账号无需审核0创建、1通过、2打回、3审核拒绝、4冻结、5删除
        userInfoDTO.setEmailActive(1);//邮箱激活 邮箱激活 0未激活，1已激活
        iUserInfoService.insert(userInfoDTO);

        /**
         * 保存用户登录表
         */
        UserLoginDTO dto = new UserLoginDTO();
        BeanUtils.copyProperties(saveBO, dto);
        String salt = Md5Utils.createSalt();
        dto.setPassword(Md5Utils.MD5Encode(dto.getPassword(), salt));//密码转换大写后加密
        dto.setSalt(salt); //密码盐
        Long id = ymlConfig.getPkId();
        dto.setId(id);
        dto.setUserId(userInfoId);//保存userID
        this.insert(dto);

        /**
         * 保存功能权限表
         */
        SysRoleSaveBO sysRoleSaveBO = new SysRoleSaveBO();
        sysRoleSaveBO.setName(saveBO.getName());
        sysRoleSaveBO.setShopId(saveBO.getShopId());
        sysRoleSaveBO.setWebType(1);//系统类型 0平台系统权限 1前端商家权限
        sysRoleSaveBO.setAuthorityIds(saveBO.getIds());
        Long roleId = iSysRoleService.add(sysRoleSaveBO);

        /**
         * 保存角色关系表
         */
        UserRoleRelationDTO userRoleRelationDTO = new UserRoleRelationDTO();
        userRoleRelationDTO.setId(ymlConfig.getPkId());
        userRoleRelationDTO.setUserId(userInfoId);//用户ID
        userRoleRelationDTO.setRoleId(roleId);// 权限ID
        iUserRoleRelationService.insert(userRoleRelationDTO);

        /**
         * 保存IM账号表
         */
        addUserIm(userInfoId);
        /**
         * 保存店员表
         */
        ShopUserRelationDTO shopUserRelationDTO = new ShopUserRelationDTO();
        Long shopUserRelationId = ymlConfig.getPkId();
        shopUserRelationDTO.setId(shopUserRelationId);
        shopUserRelationDTO.setUserId(userInfoId);
        shopUserRelationDTO.setShopId(saveBO.getShopId());
        return iShopUserRelationService.insert(shopUserRelationDTO);
    }

    @Override
    public ArrayList<UserLoginVO> queryPageListByShop(Long shopId, Integer type) {
        return baseMapper.queryPageListByShop(shopId, type);
    }

    @Override
    public Result saveRegistered(String loginVO) {
        RegisterVO registerVO = JSONObject.parseObject(loginVO, RegisterVO.class);
        RegisterVO.BaseInfoVO baseInfoVO = registerVO.getBase();
        RegisterVO.AuditInfoVO auditInfoVO = registerVO.getAudit();

        String name = baseInfoVO.getName().getValue();
        String mobile = baseInfoVO.getMobile().getValue();
        String email = baseInfoVO.getEmail().getValue();
        String contactName = baseInfoVO.getContactName().getValue();
        String address = baseInfoVO.getAddress().getValue();

        String subStatus = registerVO.getSubstatus().getValue();//提交状态
        if (StringUtils.isEmpty(subStatus)) {
            return new Result<>(CodeEnum.FAIL_100002);
        }
        Integer submitStatus = Integer.parseInt(subStatus);

        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(mobile) || StringUtils.isEmpty(email) || StringUtils.isEmpty(contactName) || StringUtils.isEmpty(address)) {
            return new Result<>(CodeEnum.FAIL_100002);
        }

        //验证是否已经被加入黑名单
        //黑名单类型 0用户黑名单，1店铺黑名单
        ShopBlacklistDTO shopBlacklistDTO = this.getByCompanyName(name, 0);
        if (shopBlacklistDTO != null) {
            return new Result<>(CodeEnum.FAIL_AddUser_3006);
        }

        if (submitStatus.equals(ShoppingCodeEnum.AUDIT_CREATE.getCode())) {
            String password = baseInfoVO.getPassword().getValue();
            String captcha = baseInfoVO.getCaptcha().getValue();
            String payMobile = baseInfoVO.getPayMobile().getValue();
            String payCaptcha = baseInfoVO.getPayCaptcha().getValue();

            //第一次提交
            if (StringUtils.isEmpty(password) || password.length() < 32) {
                return new Result<>(CodeEnum.FAIL_100002);
            }

            /**
             * 验证基本信息
             */
            //手机号验证
            if (!this.getSmsCaptcha(mobile, captcha, 0)) {
                return new Result<>(CodeEnum.FAIL_Login_1004);
            }

            //支付手机验证
            if (!this.getSmsCaptcha(payMobile, payCaptcha, 11)) {
                return new Result<>(CodeEnum.FAIL_Login_1009);
            }

            //验证公司名是否重复
            if (this.getLoginByName(name)) {
                return new Result<>(CodeEnum.FAIL_AddUser_3007);
            }

            //验证手机号是否重复
            if (this.updateByMobile(mobile)) {
                return new Result<>(CodeEnum.FAIL_AddUser_3004);
            }

            //验证邮箱是否重复
            if (this.updateByEmail(email)) {
                return new Result<>(CodeEnum.FAIL_AddUser_3005);
            }
            /**
             * 1.存储到审核表和审核日志表审核记录表
             * 2.存储各种用户关联表
             */
            //保存关联表
            /**
             * 保存用户信息表信息
             */
            UserInfoDTO userInfoDTO = addUserinfo(name, contactName, address);
            Long userInfoId = userInfoDTO.getId();
            /*
             * 保存用户登录表
             */
            addUserLog(mobile, email, userInfoId, password);
            /*
             * 保存角色关系表
             */
            addUserRoleRelation(userInfoId);
            /**
             * 保存IM账号表
             */
            addUserIm(userInfoId);
            //发送激活邮件
            sendEmail(email, userInfoId);

            //保存审核表
            addAudit(userInfoId, name, loginVO);
            return new Result<>(userInfoDTO);
        } else {
            /**
             * 1更新审核表
             * 2更新用户信息
             */
            String uId = auditInfoVO.getUserId().getValue();
            if (StringUtils.isEmpty(uId)) {
                return new Result<>(CodeEnum.FAIL_100002);
            }
            Long userId = Long.parseLong(uId);

            String aId = auditInfoVO.getAuditId().getValue();
            if (StringUtils.isEmpty(aId)) {
                return new Result<>(CodeEnum.FAIL_100002);
            }
            Long auditId = Long.parseLong(aId);

            //验证公司名是否重复 是否是自己的。
            if (getLoginReturnByName(name, userId)) {
                return new Result<>(CodeEnum.FAIL_AddUser_3007);
            }

            //更新用户信息
            updateUser(userId, name, contactName);
            //更新审核表
            updateAudit(auditId, userId, name, loginVO);
            return new Result<>();
        }
    }

    private void updateAudit(Long auditId, Long userId, String name, String loginVO) {
        AuditDTO auditDTO = new AuditDTO();
        auditDTO.setId(auditId);
        auditDTO.setCreateUserId(userId);
        auditDTO.setName(name);
        auditDTO.setParams(loginVO);
        auditDTO.setStatus(ShoppingCodeEnum.AUDIT_RESUBMIT.getCode());
        auditService.update(auditDTO);
    }

    private void updateUser(Long userId, String name, String contactName) {
        UserInfoDTO userDTO = new UserInfoDTO();
        userDTO.setId(userId);
        userDTO.setName(name);
        userDTO.setContactName(contactName);
        userDTO.setStatus(ShoppingCodeEnum.AUDIT_CREATE.getCode());//0创建，1审核通过，2审核打回，3审核不通过,4冻结、5删除
        iUserInfoService.updateById(userDTO);
    }

    private void addAudit(Long userInfoId, String name, String loginVO) {
        AuditDTO auditDTO = new AuditDTO();
        auditDTO.setCreateUserId(userInfoId);
        auditDTO.setParams(loginVO);
        auditDTO.setUserId(userInfoId);
        auditDTO.setName(name);
        auditDTO.setType(ShoppingCodeEnum.AUDIT_TYPE_LOGIN.getCode());
        auditDTO.setStatus(ShoppingCodeEnum.AUDIT_CREATE.getCode());
        auditService.add(auditDTO);
    }

    private void addUserIm(Long userInfoId) {
        UserImDTO userImDTO = new UserImDTO();
        userImDTO.setId(ymlConfig.getPkId());
        userImDTO.setUserId(userInfoId);
        iUserImService.insert(userImDTO);//类型默认买家

        UserImDTO userImSDTO = new UserImDTO();
        userImSDTO.setId(ymlConfig.getPkId());
        userImSDTO.setUserId(userInfoId);
        userImSDTO.setType(1);//卖家
        iUserImService.insert(userImSDTO);//类型默认买家
    }

    private void addUserRoleRelation(Long userInfoId) {
        UserRoleRelationDTO userRoleRelationDTO = new UserRoleRelationDTO();
        userRoleRelationDTO.setId(ymlConfig.getPkId());
        userRoleRelationDTO.setUserId(userInfoId);//用户ID
        userRoleRelationDTO.setRoleId(Long.parseLong(iSysDictService.getManagerValue()));//权限，默认店主
        iUserRoleRelationService.insert(userRoleRelationDTO);
    }

    private void addUserLog(String mobile, String email, Long userInfoId, String password) {
        UserLoginDTO dto = new UserLoginDTO();
        dto.setMobile(mobile);
        dto.setEmail(email);
        String salt = Md5Utils.createSalt();
        dto.setPassword(Md5Utils.MD5Encode(password, salt));//密码转换后加入盐大写后加密
        dto.setSalt(salt);
        dto.setId(ymlConfig.getPkId());
        dto.setUserId(userInfoId);//保存userID
        this.insert(dto);
    }

    private UserInfoDTO addUserinfo(String name, String contactName, String address) {
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        Long userInfoId = ymlConfig.getPkId();
        userInfoDTO.setId(userInfoId);
        userInfoDTO.setName(name);//公司名称
        userInfoDTO.setContactName(contactName);//联系人名称
        userInfoDTO.setAddress(address);//保存公司地址
        iUserInfoService.insert(userInfoDTO);//状态默认 0创建。类型默认 0主账号
        return userInfoDTO;
    }
}
